package com.wswy.wzcx.module.ad

import android.content.Context
import android.util.Log
import com.che.libcommon.api.ApiOptionalResultObserver
import com.che.libcommon.api.BaseResult
import com.che.libcommon.utils.JsonKit
import com.google.gson.annotations.SerializedName
import com.wswy.wzcx.BuildConfig
import com.wswy.wzcx.api.Api
import com.wswy.wzcx.api.Configs
import com.wswy.wzcx.module.RuntimeContext
import com.wswy.wzcx.utils.Tools
import java.util.*
import kotlin.random.Random

object AdConfigLoader {

    private const val TAG = "AdConfig"

    private const val CACKE_KEY = "ad_configs_2"

    //默认常规渠道
    private val NOR_CSJ_CONFIG = AdConfig(Configs.TTAD_APPID, Configs.TTAD_SPLASH_AD, Configs.TTAD_FEEDAD_AD, Configs.TTAD_BANNERAD_AD)


    @JvmStatic
    fun init(context: Context) {
        val st = System.currentTimeMillis()

        if (!RuntimeContext.isPaidChannel()) {
            requestConfig()
        }

        try {
            readNewText(context)
        } catch (e: Throwable) {
            e.printStackTrace()
        }

        Log.e(TAG, " -->ad load time: ${System.currentTimeMillis() - st} ");
    }

    private fun requestConfig() {
        Api.get().allAdIdConfig.subscribe(object : ApiOptionalResultObserver<Map<String, String?>?>() {

            override fun onApiResult(t: Map<String, String?>?) {

                t?.get("content")?.let {
                    Tools.getCache().put(CACKE_KEY, it)
                } ?: kotlin.run {
                    Tools.getCache().remove(CACKE_KEY)
                }
            }

            override fun onApiError(result: BaseResult<*>?) {
                Tools.getCache().remove(CACKE_KEY)
            }

        })
    }

    private fun findCacheConfig(context: Context): AllConfigs? {

        val ret = Tools.getCache().getString(CACKE_KEY)?.runCatching {

            JsonKit.GSON.fromJson(this, AllConfigs::class.java)
        }
        if (ret != null) {
            return ret.getOrNull()
        }

        return null
    }

    private fun readNewText(context: Context) {

        findCacheConfig(context)?.run {
            csjList?.filterNotNull()?.filter { it.canUse() }?.let {

                loadedCsjConfig = when (it.size) {

                    1 -> it.getOrNull(0)?.toAdConfig()
                    else -> getAd(it)
                }

            }

            gdtList?.filterNotNull()?.filter { it.canUse() }?.let {
                loadedGdtConfig = when (it.size) {
                    1 -> it.getOrNull(0)?.toAdConfig()
                    else -> getAd(it)
                }
            }
        }

        if (BuildConfig.DEBUG) {
            Log.e(TAG, " --> $loadedCsjConfig   $loadedGdtConfig ");
        }
    }


    private fun getAd(list: List<FlexAdConfig>): AdConfig? {
        var count = 0

        val weightMap = TreeMap<Int, FlexAdConfig>()

        list.forEach {
            count += it.weight ?: 0

            val lastWeight = if (weightMap.isEmpty()) 0 else weightMap.lastKey()

            weightMap[it.weight ?: 0 + lastWeight] = it
        }

        if (count == 0) {
            return list.first().toAdConfig()
        }

        val r = Random(System.currentTimeMillis()).nextInt(weightMap.lastKey())

        val tailMap = weightMap.tailMap(r, false)

        return weightMap[tailMap.firstKey()]?.toAdConfig()
    }


    @JvmStatic
    val gdtConfig: AdConfig by lazy {

        loadedGdtConfig
                ?: AdConfig(Configs.GDT_APP_ID, Configs.GDT_SplashPosID, Configs.GDT_HOME_AD_01_ID, Configs.GDT_JZCF_RESULT_BANNER_ID)
    }

    @JvmStatic
    val csjConfig: AdConfig by lazy {

        loadedCsjConfig ?: RuntimeContext.getPaidChannelAdConfig() ?: NOR_CSJ_CONFIG
    }


    private var loadedGdtConfig: AdConfig? = null

    private var loadedCsjConfig: AdConfig? = null


    private class AllConfigs {
        @SerializedName("gdt")
        val gdtList: List<FlexAdConfig?>? = null

        @SerializedName("csj")
        val csjList: List<FlexAdConfig?>? = null
    }

    private class FlexAdConfig {

        @SerializedName("appId")
        val appId: String? = null

        @SerializedName("splashId")
        val splashId: String? = null

        @SerializedName("feedId")
        val feedId: String? = null

        @SerializedName("bannerId")
        val bannerId: String? = null

        @SerializedName("weight")
        val weight: Int? = 0

        fun toAdConfig(): AdConfig? {
            if (canUse()) {
                return AdConfig(appId!!, splashId!!, feedId!!, bannerId!!)
            }
            return null
        }

        fun canUse(): Boolean {
            return !appId.isNullOrEmpty() &&
                    !splashId.isNullOrEmpty() &&
                    !feedId.isNullOrEmpty() &&
                    !bannerId.isNullOrEmpty()
        }

    }

}